import React, {useEffect, useState} from "react"
import {createBrowserRouter, Navigate, type RouteObject, RouterProvider} from 'react-router';
import {Loading} from "@/components/Loading";
import {getCookieToken} from "@/utils/auth";
import {usePermissions} from '@/hooks/modules/usePermissions'
import {generateRouter} from "./helper/generateRouter";
import LazyLoad from "@/components/lazyLoad";
import RouterGuard from "./helper/RouterGuard";
import CustomLoading from "@/components/Loading/components/CustomLoading";
import KeepAlive from "./helper/KeepAlive";
import type {RouteObjectType} from "@/typings/router";
import {useMenuStore} from "@/store/menu";
import useRegisterInstance from "@/hooks";


/**
 * @description 📚 路由参数配置简介
 * @param path ==> 路由菜单访问路径
 * @param element ==> 前端组件文件路径
 * @param redirect ==> 当点击面包屑目录时路由重定向地址（该属性需写在一级目录路由上）
 * @param meta ==> 路由菜单元信息
 * @param meta.key ==> 相当于vue-router的name属性(如果不设置则面包屑导航会出现问题)
 * @param meta.title ==> 路由标题 (用作 document.title || 菜单的名称)
 * @param meta.icon ==> 菜单和面包屑对应的图标（支持antd和iconPark图标），字节图标库链接（https://iconpark.oceanengine.com/official）
 * @param meta.isLink ==> 是否为外链 (如果是的话会开启新的标签页访问)
 * @param meta.hidden ==> 是否在菜单中隐藏 (通常列表详情页需要隐藏)
 * @param meta.activeMenu ==> 激活左侧菜单位置（需写在二级路由后的嵌套路由每一个meta里，主要是为了页面处于嵌套路由中默认选中并高亮一级菜单）
 * @param meta.keepAlive ==> 当前路由是否缓存(暂无法实现，由于react-router生态没有提供可用的库和组件)
 * */
const routes: RouteObjectType[] = [
    {
        path: '/',
        element: <Navigate to='/home'/>
    },
    {
        path: '/login',
        element: LazyLoad(React.lazy(() => import('@/views/login/index.tsx'))),
        meta: {title: '登录'}
    },
    {
        path: '/404',
        element: LazyLoad(React.lazy(() => import('@/components/Error/404/index.tsx')))
    },
    {
        path: '*',
        element: <Loading indicator={<CustomLoading/>}/>
    }
]

export const GlobalStaticRoutes = routes.flatMap((route: RouteObjectType) => [{
    ...route,
    // @ts-ignore
    element: <KeepAlive {...route}><RouterGuard>{route.element}</RouterGuard></KeepAlive>,
    loader: () => (route.meta ? {...route.meta} : {}),
    hydrateFallbackElement: <Loading indicator={<CustomLoading/>}/>
}])

const Router = () => {
    useRegisterInstance()
    const {initPermissions} = usePermissions()
    const {menuList} = useMenuStore()
    const [dynamicRoute, setDynamicRoute] = useState<RouteObjectType[]>(GlobalStaticRoutes)

    useEffect(() => {
        const generateSliderMenus = async () => {
            if (menuList.length) return setDynamicRoute(generateRouter(menuList))
            await initPermissions(getCookieToken())
        }
        generateSliderMenus().finally()
    }, [menuList]);

    return <RouterProvider router={createBrowserRouter(dynamicRoute as RouteObject[])}/>
}
export default Router
